#include "Reading.h"
#include <string>
#include <vector>
#include <iostream.h>
#include "Poco/Util/IniFileConfiguration.h"
#include "Poco/DateTime.h"
#include "Poco/DateTimeParser.h"
#include "Event.h"
#include <sstream>
#include "AppLogger.h"
using namespace Poco;
using namespace std;
using namespace Poco::Util;

Reading::Reading()
{

}
Reading::Reading(const string& fileName) : IniFileConfiguration(fileName)
{
	numOfEvents =0;
}

Reading::Reading(std::istream& istr) : IniFileConfiguration(istr)
{
	numOfEvents =0;
}
Reading:: ~Reading()
{
	numOfEvents =0;
}

vector<Event*> Reading::getAllTheEvents()
{
	vector<Event*> ans = vector<Event*>();
	if (numOfEvents == 0)
	{
		try
		{
			this -> getNumOfEvents();
		}
		catch (NotFoundException ex){}
	}
	for (int i =1; i <= numOfEvents;++i)
	{
		Event* event = this -> createEvent(i);
		if (event != 0)
			ans.push_back(event);
	}
	return ans;
}

double Reading:: getUserAcount()
{
	double ans = 1000;
	try
	{
		string str = this -> getProperties("GENERAL.USER_ACCOUNT");
		ans = this -> stringToDouble(str);
	}
	catch (NotFoundException ex){}
	return ans;
}
double Reading::getEnergyValue()
{
	double ans = 100;
	try
	{
		string str = this -> getProperties("GENERAL.ENERGY_VALUE");
		ans = this -> stringToDouble(str);
	}
	catch (NotFoundException ex){}
	return ans;
}
bool Reading::getSayaON()
{
	bool ans = true;
	try
	{
		string str = this -> getProperties("GENERAL.SAYA_ON");
		if (str == "OFF")
			ans = false;
	}
	catch (NotFoundException ex){}
	return ans;

}
int Reading::getSayaBuing()
{
	int ans = 20;
	try
	{
		string str = this -> getProperties("GENERAL.SAYA_BUYING");
		ans = this -> stringToInt(str);
	}
	catch (NotFoundException ex){}
	return ans;
}
int Reading::getLoggerConsolePriority()
{
	int ans = 6;
	try
	{
		string str = this -> getProperties("GENERAL.LOGGER_CONSOLE_PRIORITY");
		ans = this -> stringToInt(str);
	}
	catch (NotFoundException ex){}
	return ans;
}
int Reading::getLoggerFilePriority()
{
	int ans = 5;
	try
	{
		string str = this -> getProperties("GENERAL.LOGGER_FILE_PRIORITY");
		ans = this -> stringToInt(str);
	}
	catch (NotFoundException ex){}
	return ans;
}

Event* Reading::createEvent(int index)
{
	string type, strDate, strID="",energyType="",strNumberOfUnits= "0",strPrice = "0";
	string event = "EVENT";
	string strIndex = intToString(index);
	int numberOfUnits,timeZoneDiff;
	strPrice = "0";
	double price =0;
	DateTime date;
	event+=strIndex;
	event+=".";
	Event* ans=0;
	try
	{
		type = this ->getProperties(event+"Type");
		strDate = this ->getProperties(event+"Date");
		try
		{
			strID = this ->getProperties(event+"UserID");
		}
		catch (NotFoundException ex) { }
		try
		{
			energyType = this ->getProperties(event+"EnergyType");
		}
		catch (NotFoundException ex){ }
		try
		{
			strNumberOfUnits = this ->getProperties(event+"NumberOfUnits");
		}
		catch (NotFoundException ex) { }
		try
		{
			strPrice = this ->getProperties(event+"PricePerUnit");
		}
		catch (NotFoundException ex) { }
		//cout<<strDate<<endl;
		if (!DateTimeParser::tryParse("%d/%n/%Y", strDate, date, timeZoneDiff))
		{
			CAppLogger::Instance().Log("Error evetns data is not consistent",Message::PRIO_ERROR);
			return ans;
		}
		numberOfUnits = this -> stringToInt( strNumberOfUnits);
		price = this -> stringToDouble(strPrice);
//		bool energytype = validEnergy(energyType) , eventtype = validEventType(type), validuser = validUser(strID);
//		cout<<"testing for energy type + eventtype + valid user "<<energytype<< eventtype<<validuser<<endl;
		if (this -> validEnergy(energyType) & this -> validEventType(type) & this -> validUser(strID))
		{
			if (price>=0& numberOfUnits>=0)
			{
				ans = new Event(date,strID,energyType,type,numberOfUnits,price);
			}
		}
	}
	catch (NotFoundException ex)
	{
		CAppLogger::Instance().Log("Error evetns data is not consistent",Message::PRIO_ERROR);
	}
	return ans;
}

bool Reading::validUser(string userName)
{
	return (userName == "13" || userName== "19" || userName =="22" ||userName =="32" || userName =="51"
		||userName =="59"||userName =="62"||userName =="75"||userName =="88"||
		userName =="95"||userName =="99"|| userName =="");

}


bool Reading::validEnergy(string energyType)
{
	return (energyType == "coal" || energyType == "hug" || energyType == "gas" || energyType == "oil" ||
			energyType == "smile" || energyType == "sun" || energyType == "wind" || energyType=="");
}


bool Reading::validEventType(string eventType)
{
	return (eventType=="create"||eventType=="consume"||eventType=="sell"||eventType=="buy"||
			eventType=="userReport"||eventType=="energyReport"||eventType=="accountReport"||
			eventType=="profitReport"||eventType=="activityReport");

}


string Reading::intToString(int index)
{
	string ans;
	stringstream out;
	out << index;
	ans = out.str();
	return ans;
}

//Events Reading::getBuyingEvents()
//{
//	if (numOfEvents ==0)
//	this -> getNumOfEvents();
//	Events ans
//	return ans;
//}

void Reading::getNumOfEvents()
{
		string num = getProperties("numberOfEvents");
		numOfEvents = stringToInt(num);
}

int Reading::stringToInt(string str)
{
	istringstream buffer(str);
	int ans;
	buffer >> ans;
	return ans;
}

double Reading::stringToDouble(string str)
{
	istringstream buffer(str);
	double ans;
	buffer >> ans;
	return ans;

}

string Reading::getProperties(string properties)
{
	ostringstream stringFromFile;
	stringFromFile <<properties;
	string ans = getString(stringFromFile.str());
	return ans;
}

string Reading::doubleToString(double index)
{
	string ans;
	stringstream out;
	out << index;
	ans = out.str();
	return ans;
}


